package fixture;

import java.io.IOException;
import java.io.Serializable;
import java.net.InetAddress;
import java.sql.SQLException;
import java.util.ArrayList;

import vcp.client.exceptions.EmptyRequestException;
import vcp.client.forms.SubscriptionCancelForm;
import vcp.client.request.CancelSubscriptionFormRequest;
import vcp.client.request.Request;
import vcp.client.request.UserLoginRequest;
import vcp.client.request.UserLogoutRequest;
import vcp.client.request.response.ResponseRequest;
import vcp.entity.Car;
import vcp.entity.Customer;
import vcp.entity.Subscription;
import vcp.server.DBAdapter;
import vcp.server.utility.timedecision.TimeDecisionMinute;
import clientserver.DummyServer;
import clientserver.DummyUIRootModel;
import fit.ActionFixture;

/**
 * 
 * @author VCP team
 * 
 *         <p>
 *         This class is responsible for testing the correct functionality on
 *         when user tries to cancel order more then 3 hours due to his
 *         requested subscription
 *         </p>
 */
public class OrderCancelation3HoursBeforeFixture extends ActionFixture
{
	protected DummyServer server;
	protected DummyUIRootModel client;

	protected int customerID;
	protected String customerPassword;

	protected Customer customer;
	protected Subscription deletedSubscription;
	protected Float originBalance;
	protected Float refundBalance;

	public OrderCancelation3HoursBeforeFixture()
	{
		super();
		this.customerID = 312345696;
		this.customerPassword = "8";
	}

	// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// Customer login
	// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/**
	 * performs a login with a customer
	 * 
	 * @return true if login success
	 */
	public boolean customerLogin()
	{
		this.sendToServer(new UserLoginRequest(this.customerID, this.customerPassword));
		this.client.waitForResponse();

		this.customer = (Customer) this.client.getResponse().getData();
		return this.customer != null;
	}

	/**
	 * log's out customer
	 */
	public void customerLogout()
	{
		this.sendToServer(new UserLogoutRequest());
		System.out.println("logged out");
	}

	// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// Customer order cancellation
	// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	@SuppressWarnings("unchecked")
	/**
	 * performs a cancel subscription request
	 * @return true if customer was able to cancel his order
	 */
	public boolean customerOrderCancelSuccess()
	{
		this.originBalance = this.customer.getBalance();

		Subscription subscription = this.customer.getSubscriptions().get(0);
		Car car = subscription.getCars().get(0);

		SubscriptionCancelForm cancelForm = new SubscriptionCancelForm(subscription.getSubscribtionID(), car.getCarID());
		cancelForm.setSubscription(subscription);
		this.sendToServer(new CancelSubscriptionFormRequest(cancelForm));
		this.client.waitForResponse();

		ResponseRequest responseRequest = this.client.getResponse();
		ArrayList<Serializable> serialList = (ArrayList<Serializable>) responseRequest.getData();
		this.deletedSubscription = (Subscription) serialList.get(0);
		this.refundBalance = (Float) serialList.get(1);

		return this.deletedSubscription.isDeleted();
	}

	/**
	 * 
	 * @return true if customer balance was changed
	 */
	public boolean customerBalanceChange()
	{
		return this.originBalance.floatValue() != this.refundBalance.floatValue();
	}

	/**
	 * 
	 * @return updated customer balance
	 */
	public float customerBalanceVerification()
	{
		return this.refundBalance.floatValue();
	}

	// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// Protected methods
	// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/**
	 * send the {@link Request} to server via client
	 * 
	 * @param request
	 */
	protected void sendToServer(Request request)
	{
		try
		{
			this.client.registerAndSendRequest(request, null);
		}
		catch (EmptyRequestException e)
		{
			e.printStackTrace();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// Setup
	// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/**
	 * Initialization of Late arrival test
	 */
	public void setUp()
	{
		try
		{
			this.server = new DummyServer(5555, new TimeDecisionMinute());
			this.server.listen();

			Thread.sleep(1000);

			this.client = new DummyUIRootModel();
			this.client.connectToServer(InetAddress.getLocalHost().getHostAddress(), 5555);

			Thread.sleep(1000);
			System.out.println("up");
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * DB modification according to the test requirements
	 */
	public void dbChange()
	{
		String subscriberArrivalUpdate = "UPDATE `vcp`.`subscriptions` SET `arrivalDate`='2014-01-10 12:00:00', "
				+ "`estimatedLeaveDate`='2014-01-10 13:00:00' WHERE `subscriptionID`='38' and`customerID`='" + this.customerID + "';";

		try
		{
			DBAdapter.getAdapter().refresh(subscriberArrivalUpdate);
		}
		catch (SQLException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * Restoring DB previous to test
	 */
	public void dbCleanUp()
	{
		String subscriptionRemoveFromHistory = "DELETE FROM `vcp`.`subscriptionhistory` WHERE `subscriptionID`='38' and`customerID`='312345696';";
		String restoreSubscription = "INSERT INTO `vcp`.`subscriptions` VALUES (38,312345696,\"Site 2\",\"Order Ahead Customer\",\"2013-12-16 13:09:57\",\"2014-01-28 05:35:57\",\"2014-01-01 00:00:00\",\"2014-01-01 00:00:00\");";
		String restoreCar = "INSERT INTO `vcp`.`cars` VALUES (3245654,38,312345696,0,\"2001-01-01 00:00:00\",\"2001-01-01 00:00:00\");";

		String restoreSiteReserved = "UPDATE `vcp`.`site` SET `reservedLots`='0' WHERE `siteID`='2';";
		String restoreLotReserved = "UPDATE `vcp`.`lot` SET `status`='Reserve', `carID`='3245654', `reservedBySubscription`='38' WHERE `lotFloor`='1' and`lotRow`='1' and`lotColumn`='1' and`siteID`='2';";

		String restoreCustomerDetails = "UPDATE `vcp`.`customer` SET `bussinessClass`='1', `balance`='900' WHERE `customerID`='312345696';";

		String[] sqlStatements = new String[]
		{ subscriptionRemoveFromHistory, restoreSubscription, restoreCar, restoreSiteReserved, restoreLotReserved, restoreCustomerDetails };

		for (String string : sqlStatements)
		{
			try
			{
				DBAdapter.getAdapter().refresh(string);
			}
			catch (SQLException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	/**
	 * kill test initialization
	 */
	public void tearDown()
	{
		try
		{
			this.client.closeConnection();
			this.server.stopListening();
			this.server.close();

			this.client = null;
			this.server = null;
			System.out.println("down");
		}
		catch (IOException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
